package cn.ywang.spring.customized.framework.context.support;

import cn.ywang.spring.customized.framework.beans.BeanDefinition;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 对配置文件进行 查找 解析
 *
 * @author BeatificWang
 * @date 2018/11/5 22:34
 */
public class XmlBeanDefinitionReader {

	/**
	 * 在配置文件中 用来获取自动扫描的包
	 */
	private static final String SCAN_PKG = "scanPkg";

	/**
	 * 配置文件内容的载体形式
	 */
	private Properties contextConfig = new Properties();

	/**
	 * 记录被扫描包下的所有类名，带包名
	 */
	private List<String> registryBeanClasses = new ArrayList<>();

	/**
	 * 扫描指定包下的类
	 *
	 * @param locations
	 */
	public XmlBeanDefinitionReader(String... locations) {
		// spring中是通过Reader去查找和定位的
		InputStream input = null;
		try {
			for (String location : locations) {
				input = this.getClass()
						        .getClassLoader()
						        .getResourceAsStream(locations[0].replace("classpath:", ""));
				this.contextConfig.load(input);
				this.doScanner(this.contextConfig.getProperty(SCAN_PKG));
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				input = null;
			}
		}
	}

	/**
	 * 递归扫描包下的所有类，并保存到一个registryBeanClasses
	 *
	 * @param pkgName
	 */
	private void doScanner(String pkgName) {
		URL url = this.getClass().getClassLoader().getResource("/" + pkgName.replaceAll("\\.", "/"));
		if (url == null || url.getFile() == null) {
			return;
		}
		File classDir = new File(url.getFile());
		File[] files = classDir.listFiles();
		if (files == null) {
			return;
		}
		for (File file : files) {
			if (file.isDirectory()) {
				this.doScanner(pkgName + "." + file.getName());
			}
			else {
				this.registryBeanClasses.add(pkgName + "." + file.getName().replaceAll(".class", ""));
			}
		}
	}

	/**
	 * 每注册一个class，返回一个BeanDefinition
	 *
	 * @param className
	 * @return
	 */
	public BeanDefinition registerBeanDefinitions(String className) {
		if (this.registryBeanClasses.contains(className)) {
			BeanDefinition beanDefinition = new BeanDefinition();
			beanDefinition.setBeanClassName(className);
			beanDefinition.setFactoryBeanName(this.lowerFirstCase(className.substring(className.lastIndexOf(".") + 1)));
			return beanDefinition;
		}
		return null;
	}

	public Properties getContextConfig() {
		return this.contextConfig;
	}

	public List<String> getRegistryBeanClasses() {
		return this.registryBeanClasses;
	}

	/**
	 * 首字母小写
	 *
	 * @param string
	 * @return
	 */
	private String lowerFirstCase(String string) {
		if (StringUtils.isBlank(string)) {
			return "";
		}
		char[] chars = string.toCharArray();
		chars[0] += 32;
		return String.valueOf(chars);
	}

	public List<String> loadBeanDefinitions() {
		return this.getRegistryBeanClasses();
	}
}
